package com.zhuangjie.security.utils;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAUtils {
    /**
     * 生成 RSA 密钥对
     *
     * @return 密钥对
     * @throws Exception 如果生成密钥对失败
     */
    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048); // 设置密钥长度为 2048
        return keyGen.generateKeyPair();
    }

    /**
     * 使用私钥对数据进行签名
     *
     * @param data       要签名的数据
     * @param privateKey 私钥
     * @return 签名结果
     * @throws Exception 如果签名过程中出现错误
     */
    public static String sign(String data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes(StandardCharsets.UTF_8));

        byte[] signBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signBytes);
    }

    /**
     * 使用公钥验证签名
     *
     * @param data      原始数据
     * @param signature 签名
     * @param publicKey 公钥
     * @return 验证通过返回 true，否则返回 false
     * @throws Exception 如果验证过程中出现错误
     */
    public static boolean verify(String data, String signature, PublicKey publicKey) throws Exception {
        Signature verifier = Signature.getInstance("SHA256withRSA");
        verifier.initVerify(publicKey);
        verifier.update(data.getBytes(StandardCharsets.UTF_8));

        byte[] signatureBytes = Base64.getDecoder().decode(signature);
        return verifier.verify(signatureBytes);
    }

    /**
     * 将私钥转换为字符串
     *
     * @param privateKey 私钥
     * @return 私钥字符串
     */
    public static String privateKeyToString(PrivateKey privateKey) {
        byte[] privateKeyBytes = privateKey.getEncoded();
        return Base64.getEncoder().encodeToString(privateKeyBytes);
    }

    /**
     * 将公钥转换为字符串
     *
     * @param publicKey 公钥
     * @return 公钥字符串
     */
    public static String publicKeyToString(PublicKey publicKey) {
        byte[] publicKeyBytes = publicKey.getEncoded();
        return Base64.getEncoder().encodeToString(publicKeyBytes);
    }

    /**
     * 将私钥字符串转换为私钥对象
     *
     * @param privateKeyString 私钥字符串
     * @return 私钥对象
     * @throws Exception 如果转换失败
     */
    public static PrivateKey privateKeyFromString(String privateKeyString) throws Exception {
        // 对privateKey进行一些操作，最后使用下面的privateKey，如果直接使用私钥，那会报错
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 将公钥字符串转换为公钥对象
     *
     * @param publicKeyString 公钥字符串
     * @return 公钥对象
     * @throws Exception 如果转换失败
     */
    public static PublicKey publicKeyFromString(String publicKeyString) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        return keyFactory.generatePublic(keySpec);
    }
}